/**
 * @file flash.c
 * @author mengjun@eav.top
 * @brief 
 * @version 0.2
 * @date 
 * 2022-11-02 the first version
 * 
 * @copyright Copyright (c) 2022
 * 
 */

#include "flash.h"



/**
 * @brief flash_read
 * 
 * @param len 
 * @param outdata 
 * @param addr_start 
 */
void flash_read(uint16_t len,uint8_t *outdata,uint32_t addr_start)
{	
	uint32_t addr;
	uint16_t i;
	
	addr = addr_start;
	
	for(i=0;i<len;i++) 
	{
		*outdata = *(uint8_t*) addr;
		addr = addr + 1;
		outdata++;
	}
}

/**
 * @brief u8_flash_write
 * 
 * @param len 
 * @param data 
 * @param addr_start 
 */
void u8_flash_write(uint32_t len,uint8_t  *data,uint32_t addr_start)
{	
	uint32_t i;
	uint32_t temp;
	
	fmc_state_enum  fmc_state=FMC_READY;
	
	fmc_unlock();
	
	fmc_flag_clear(FMC_FLAG_BANK0_END);
	fmc_flag_clear(FMC_FLAG_BANK0_WPERR);
	fmc_flag_clear(FMC_FLAG_BANK0_PGERR);

	for(i=0;i<len/2;i++) 
	{
		fmc_state=fmc_halfword_program(addr_start, *(uint16_t*)data);
		
		if(fmc_state!=FMC_READY)
		{
			return;
		}
		
		fmc_flag_clear(FMC_FLAG_BANK0_END);
		fmc_flag_clear(FMC_FLAG_BANK0_WPERR);
		fmc_flag_clear(FMC_FLAG_BANK0_PGERR);
		
		data += 2;
		addr_start += 2;
	}
	if(len % 2)
	{
		temp = *data | 0xff00;
		fmc_state=fmc_halfword_program(addr_start,temp);
	}

	fmc_lock();
}


/**
 * @brief flash_erase
 * 
 * @param start 
 * @param end 
 */
void flash_erase(uint32_t start, uint32_t end)
{
	uint32_t EraseCounter;
	
	fmc_state_enum fmc_state=FMC_READY;

	  /* unlock the flash program/erase controller */
    fmc_unlock();

    /* clear all pending flags */
    fmc_flag_clear(FMC_FLAG_BANK0_END);
    fmc_flag_clear(FMC_FLAG_BANK0_WPERR);
    fmc_flag_clear(FMC_FLAG_BANK0_PGERR);
    
    /* erase the flash pages */
    while(start < end)
	{
		EraseCounter = start/FLASH_PAGE_SIZE;
        fmc_state=fmc_page_erase(EraseCounter*FLASH_PAGE_SIZE);
		if(fmc_state!=FMC_READY)
		{
			return;
		}
        fmc_flag_clear(FMC_FLAG_BANK0_END);
        fmc_flag_clear(FMC_FLAG_BANK0_WPERR);
        fmc_flag_clear(FMC_FLAG_BANK0_PGERR);
			 
		start += FLASH_PAGE_SIZE;
    }

    /* lock the main FMC after the erase operation */
    fmc_lock();
}



